<template>
  <div v-move class="box">
    <div class="header"></div>
    <div class="content"></div>
  </div>
</template>
<script setup lang="ts">
import { Directive } from 'vue'

// 自定义指令 v-move 实现拖拽功能
const vMove: Directive<any, void> = (el: HTMLDivElement) => {
  // 获取 box 元素的 header 子元素 采用断言形式确定其非 null
  const header: HTMLDivElement = el.firstElementChild as HTMLDivElement
  // 鼠标点击事件，点击 header 元素
  const mousedown = (e: MouseEvent) => {
    // x y 为 el 鼠标点击位置到元素中点位置的差值
    let x = e.clientX - el.offsetLeft
    let y = e.clientY - el.offsetTop
    console.log(x, y)
    // 鼠标移动事件，在整个页面上移动
    const mosemove = (e: MouseEvent) => {
      el.style.left = e.clientX - x + 'px'
      el.style.top = e.clientY - y + 'px'
    }
    // 因为在页面上移动，故事件添加到 document 上
    document.addEventListener('mousemove', mosemove)
    // 鼠标松开事件，松开鼠标，在 document 上清除鼠标移动事件
    const moseup = () => {
      console.log('up')
      document.removeEventListener('mousemove', mosemove)
    }
    // 将鼠标松开事件添加到 document 上
    document.addEventListener('mouseup', moseup)
  }
  header.addEventListener('mousedown', mousedown)
}
</script>
<style lang="less" scoped>
.box {
  height: 200px;
  width: 200px;
  position: absolute;
  top: 50%;
  left: 50%;
  // transfrom 变换，使用 translate 平移变换
  transform: translate(-100px, -100px);
  border: 1px solid black;
  .header {
    height: 40px;
    background-color: black;
  }
}
</style>
